home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 July / Macworld (1999-07).dmg / Shareware World / Info / For Developers / Mops 3.4.sea / Mops source / Toolbox classes / AppleEvents < prev    next >
Text File  |  1997-09-29  |  8KB  |  280 lines

  1. \ 10Dec93 DBH  initial version
  2. \ 12Feb94 DBH added proper disposal of AppleEvent and Reply via AEDisposeDesc at each and
  3. \ every time we send an AppleEvent. Before, this was causing memory to be consumed and never
  4. \ freed at each send.
  5.  
  6.  \ It is interesting that, with this scheme at least, it is
  7.  \ not necessary to create and dispose the description record QEdesc at each send.
  8.  
  9. \ See general comments at the end of this file.
  10.  
  11.  
  12. \ This AppleEvent class is at the moment geared to sending AEs to
  13. \ Quick Edit.  But it wouldn't be too hard to make it more general.
  14.  
  15. syscall AECreateDesc
  16. syscall AEDisposeDesc
  17. syscall AESend
  18. syscall AECreateAppleEvent
  19.  
  20.  
  21. :class AEDesc super{ object }
  22.  
  23. 68k_record
  24. {    longword    descriptorType
  25.     handle        dataHandle        \ first 4 bytes of handle will = MSET after new:
  26.     var            dataPtr
  27. }
  28.  
  29. :m classinit:
  30.     'type MSET put: dataPtr        \ put QE creator signature in a dataPtr
  31.     ;m
  32.  
  33. :m new:
  34.     'type sign        \ typeApplSignature
  35.     addr: dataPtr
  36.     8                \ dataSize
  37.     ^base            \ VAR result -> our record
  38.     AECreateDesc
  39.     IF ." failed to create AE Desc record" THEN
  40.     ;m
  41.  
  42. :m release:
  43.     ^base        \ VAR theAEDesc -> our record
  44.     AEDisposeDesc  \ here we actually use AEDisposeDesc to dispose an AEDesc
  45.     IF ." failed to dispose AE Desc record" THEN
  46. ;m
  47.  
  48. ;class
  49.  
  50. AEDesc QEdesc
  51.  
  52.  
  53.  
  54. variable dummyReply 16 allot
  55.  
  56. :class AppleEvent super{ object }
  57.  
  58. 68k_record
  59. {    int    what
  60.     var    mclass
  61.     var    when
  62.     var    mID
  63.     int    modifiers
  64.     var theClass    \ will be 'type OPEN or TEXT for now.  Could be other things later.
  65. }
  66.  
  67. \ :m classinit: \ 12Feb94 DBH   necessary???  apparently not
  68. \    konst kHighLevelEvent put: what ;m
  69.  
  70. \ Guess what?  We have to dispose of our AppleEvent AFTER EACH SEND !
  71. \ and we must use AEDisposeDesc.  This was not immediately obvious to me from IM.
  72. \ Also, we must dispose of our reply, again using AEDisposeDesc.  AEDisposeDesc seems to be
  73. \ the universal dispoz-all for AE things.  The penalty for not doing this is lost heap at every
  74. \ send.
  75.  
  76. :m release:     \ 12Feb94 DBH
  77.     ^base  AEDisposeDesc
  78.     IF ." failed to dispose of AppleEvent" THEN
  79.     
  80.     dummyReply  AEDisposeDesc
  81.     IF ." failed to dispose of Reply" THEN
  82.     ;m
  83.  
  84. :m new:    { theClass theID -- }    \ theID MUST be a handle
  85.     theClass
  86.     theID
  87.     QEdesc            \ we are always using this target here
  88.     konst kAutoGenerateReturnID
  89.     0                \ konst AnyTransactionID \ no call?
  90.     ^base            \ VAR result will be our own ivar record , but only using ivars
  91.                     \  through modifiers
  92.     AECreateAppleEvent
  93.     IF " failed to create AppleEvent" cr THEN ;m
  94.  
  95. \ :m set:  ( AEEventClass -- ) \ 12Feb94 DBH incorporated into new:
  96. \    put: theClass ;m
  97.  
  98. :m send:    ( -- oserr )
  99.     ^base    \ we are sending ourself, of course
  100.     dummyReply
  101.     konst kAEWaitReply        \ sendmode, we must wait for reply so we don't
  102.                             \  clobber the handle
  103.                             \  before QE has a chance to deal with it.
  104.     konst kAENormalPriority            \ sendPriority
  105.     konst kAEDefaultTimeout            \ timeoutinticks  see IM-VI 6-94
  106.     0                        \ idleproc
  107.     0                        \ filterproc
  108.     AESend
  109.     ;m
  110.     
  111.  
  112. ;class
  113.  
  114.  
  115. :class QEopen super{ object }
  116.  
  117. record
  118. {    byte fileNameLength
  119.     32 bytes fileName
  120.     int volRef#
  121.     var dirID
  122.     var selStart
  123.     var SelEnd
  124. }
  125.  
  126. :m put: { ^obj n1 n2 -- }    \  file object and desired selection range
  127.     getname: [ ^obj ]  ( addr len )
  128.     32 min  dup put: fileNameLength  addr: fileName  swap  cmove    \ ala ctl example
  129.     
  130.     getvref: [ ^obj ]  put: volRef#
  131.     getdirID: [ ^obj ]  put: dirID
  132.     n1 put: selStart
  133.     n2 put: SelEnd ;m
  134.  
  135. :m length:  ( -- n )  \ can't send this message to an ivar!!
  136.     48 ;m
  137.  
  138. ;class
  139.  
  140.  
  141. \ This class will be used as our sole communication device to QE when sending AEs.
  142.  
  143. PPC?
  144. [IF]
  145. :class QE super{ object }
  146.  
  147.     AppleEvent    QEevent
  148.     QEopen        tQEopen
  149.     string        QEstr
  150.     
  151. [ELSE]
  152.  
  153. :class QE super{ object }
  154.  
  155.     AppleEvent    QEevent
  156.     QEopen        tQEopen
  157.     string+        QEstr
  158.     
  159. [THEN]
  160.  
  161. :m new:
  162.     new: QEstr
  163.     new: QEdesc        \ note that QEdesc is a public object
  164.     ;m
  165.  
  166. :m release:
  167.     release: QEstr
  168.     release: QEdesc
  169.     ;m
  170.  
  171. :m send:  ( theClass -- oserr ) \ 12Feb94 DBH must new: and release: for each send!!
  172.     handle: QEstr ( ID )  new: QEevent    \ always using QEstr handle as our ID.  
  173.     send: QEevent
  174.     clear: QEstr    \ 12Feb94 DBH must always clear the string because next action
  175.                     \ may be to simply add as when doing a text:
  176.     release: QEevent
  177.     ;m
  178.  
  179. :m openFile:  ( ^obj n1 n2 -- oserr )    \ file object and selection range
  180.     put: tQEopen
  181.     addr: tQEopen  length: tQEopen  put: QEstr
  182.     'type OPEN  send: self ;m
  183.  
  184. :m text:  ( addr len -- )        \ text to be "typed" into front QE window
  185.                                     \ if no window open in QE, no action from QE, just a beep
  186. \    put: QEstr     \ 27Jan94 DBH
  187. \    'type TEXT send: self ;m
  188.     add: QEstr ;m
  189.  
  190. variable emitvar 4 allot
  191.  
  192. :m cr:    ( -- oserr )
  193.     13 emitvar c!
  194.     emitvar 1 text: self
  195.     'type TEXT send: self
  196.     clear: QEstr ;m
  197.  
  198. :m newWindow: ( addr len -- oserr )    \ opens a new window in QE, does not create a file on disk
  199.                                     \ if no more available windows in QE, no action, just a beep
  200.     put: QEstr
  201.     'type NEWF send: self ;m
  202.  
  203. :m putRect:  ( l t r b -- oserr )    \ will set the front QE window portrect to these values
  204.                                     \ if no window open in QE, no action from QE, just a beep
  205.     put: temprect
  206.     addr: temprect 8 put: QEstr
  207.     'type RECT  send: self ;m
  208.  
  209. :m find:  ( addr len -- oserr )  \ will request that QE find first occurrence of
  210.     \ the given text in the front qe window.  We are limited to strings of length
  211.     \ 255 and less.  All searches will be case insensitive.
  212.     put: QEstr
  213.     >uc: QEstr            \ QE needs all upper case for this
  214.     'type FIND send: self ;m
  215.     
  216. ;class
  217.  
  218. QE tQE        \ we now have just one object for sending commands to Quick Edit
  219.  
  220.  
  221. : inittQE
  222.     instld?  ?EXIT            \ Mustn't do this in installed apps
  223. [ ppc? not ]
  224. [if]
  225.     AppleEvents?  0EXIT
  226. [then]
  227.     new: tQE  ;
  228.  
  229. inittQE
  230.  
  231. ' inittQE add: init_actions
  232.  
  233. endload
  234.  
  235. +echo
  236.  
  237. file testfile
  238.  
  239. : GO1
  240.     'type TEXT 1 stdget: testfile .  cr
  241.     testfile 10 20  openFile: tQE . ;
  242.  
  243. : GO2
  244.     " Hello World" text: tQE cr: tQE . ;    \ note how we must always end with a cr: to send:
  245.  
  246. : GO3
  247.     " My File Name" newwindow: tQE . ;
  248.  
  249. : GO4
  250.     100 50 300 350 putrect: tQE . ;
  251.  
  252. endload
  253.  
  254. ****** GENERAL COMMENTS *******
  255.  
  256.  
  257. It is very important to understand the "trick" being used here for communication between Mops and 
  258. QE.  We follow Apple's recipe for everything except for the descriptor record scheme.  Instead of 
  259. building and then deciphering the seemingly overly complex descriptor records for each AE, it seemed 
  260. to me to be much more straightforward to just send a handle to whatever data structure we wish.  
  261. Since we control everything at both ends (Mops and QE), then why go through all of the gyrations of 
  262. the AEdesc record handling?  We avoid having to deal with any of the AEPutParam/AEGetParam etc.  
  263. Also, we don't even have to deal with AEInstallEventHandler or AEProcessAppleEvent!
  264.  
  265. What we do is to only define our AppleEvents by class and not by also providing an ID.  This does 
  266. not seem to be much of a limitation on defining AEs since there are certainly plenty of different 
  267. classes we could define with the 32 bit class identifier.  Most importantly, we have now freed up 
  268. the ID of our AE for use in any way that we wish, and we wish to make our ID the handle to the data 
  269. we want to pass from Mops to QE or vice versa.  I don't know what kind of problems this could cause.  
  270. To date, I have noticed no problems.  But this does not seem to be the way Apple intended.  So 
  271. beware.  Note that both Mops and QE accomplish AE communication in exactly the same (non-standard) 
  272. way.  
  273.  
  274. The memory problem that both QE 2.4 and the original Mops 2.4 release suffered was not related
  275. to this scheme.  That problem existed due to the lack of understanding on my part of the need for
  276. disposing AppleEvents and AE Replies after each AESend.  But note that we do not need to create
  277. and dispose our descriptor record itself.  But we must use AEDisposeDesc to dispose of the 
  278. AppleEvent and AEReply ( no AEDisposeAppleEvent exists, apparently).
  279.  
  280. -Doug Hoffman  \ 12Feb94